/*
 * Copyright (c) 2024 iSOFT INFRASTRUCTURE SOFTWARE CO., LTD.
 * easyAda is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *          http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */

#ifndef ENDPOINT_H
#define ENDPOINT_H

#include <stdlib/stdint.h>

#include <tools/list.h>

#include <core/object.h>

typedef struct endpoint {
    object_t       obj;
    list_t         waiters;
    void          *server;
    unsigned short state;
    unsigned short free;
} DEFAULT_ALINMENT endpoint_t;

enum ep_state { EP_IDLE = 0, EP_SEND, EP_RECV, EP_DIED };

static inline void endpoint_get(endpoint_t *ep)
{
    object_get(&ep->obj); /* PRQA S 3200 */
}

static inline void endpoint_put(endpoint_t *ep)
{
    object_put(&ep->obj, offset_of(endpoint_t, obj), sizeof(endpoint_t)); /* PRQA S 3200, 3432 */
}

struct task_control_block;
typedef struct task_control_block tcb_t;

void endpoint_init(endpoint_t *ep);
void endpoint_send(endpoint_t *ep, unsigned int tag, unsigned long m0, unsigned long m1, unsigned long m2,
                   unsigned long m3, unsigned long m4, unsigned long m5, void *_sender);
void endpoint_receive(endpoint_t *ep, unsigned int tag, tcb_t *receiver);
void endpoint_call(endpoint_t *ep, unsigned int tag, unsigned long m0, unsigned long m1, unsigned long m2,
                   unsigned long m3, unsigned long m4, unsigned long m5, void *_caller);
int  endpoint_reply(endpoint_t *ep, unsigned int tag, unsigned int m0, unsigned int m1, unsigned long m2,
                    unsigned long m3, unsigned long m4, unsigned long m5, void *_replier);
void endpoint_reply_wait(endpoint_t *ep, unsigned int tag, unsigned int m0, unsigned int m1, unsigned long m2,
                         unsigned long m3, unsigned long m4, unsigned long m5, void *replier);
void endpoint_cancel(endpoint_t *ep);
void endpoint_clean_callers(tcb_t *tsk);
void endpoint_bind(endpoint_t *ep, tcb_t *tsk);
void endpoint_unbind(endpoint_t *ep, tcb_t *tsk);

#endif
